// lock.cpp
// Copyright (C) 2008 Sam Bateman
// samuel.bateman@gmail.com
//
// This file is part of DVD On Fire.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! @file lock.cxx
//! @author Sam Bateman
//! @brief Source file for the Lock class.

#include <pthread.h>
#include "lock.h"

namespace dvdonfire
{
    namespace lib
    {
        // struct Lock<T>::Impl {{{
        template <typename T>
        struct Lock<T>::Impl
        {
            pthread_mutex_t mutex;
            T               object;
        };
        // }}}
        // Lock<T>::Lock() {{{
        //! @brief Constructor.
        //! @param value Initial value for locked object.
        template <typename T>
        Lock<T>::Lock(const T& value)
        {
            impl = new Impl;
            impl->object = value;
            pthread_mutex_init(&impl->mutex, NULL);
        }
        // }}}
        // Lock<T>::~Lock() {{{
        //! @brief Destructor.
        template <typename T>
        Lock<T>::~Lock()
        {
            pthread_mutex_destroy(&impl->mutex);
            delete impl;
        }
        // }}}
        // Lock<T>::get() {{{
        //! @brief Returns the locked object.
        //! @return The locked object.
        template <typename T>
        T& Lock<T>::get()
        {
            return impl->object;
        }
        // }}}
        // Lock<T>::get() const {{{
        //! @brief Returns the locked object.
        //! @return The locked object.
        template <typename T>
        const T& Lock<T>::get() const
        {
            return impl->object;
        }
        // }}}
        // Lock<T>::lock() {{{
        //! @brief Locks the object.
        //!
        //! Locks the stored object.  If more than one thread calls this
        //! function, all but the first will block until unlock() is called.
        template <typename T>
        void Lock<T>::lock()
        {
            pthread_mutex_lock(&impl->mutex);
        }
        // }}}
        // Lock<T>::unlock() {{{
        //! @brief Unlocks the object.
        //!
        //! Unlocks the stored object.  If several threads are blocked in a
        //! call to lock(), this releases one of them (which one is
        //! system-dependent).
        template <typename T>
        void Lock<T>::unlock()
        {
            pthread_mutex_unlock(&impl->mutex);
        }
        // }}}
        // Lock<T>::set(value) {{{
        //! @brief Sets the locked object.
        //! @param value to set the object to.
        template <typename T>
        void Lock<T>::set(const T& value)
        {
            impl->object = value;
        }
        // }}}
    }
}
